/*
 * ====================================================================
 * Copyright (c) 2002-2018 The RapidSVN Group.  All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (in the file GPL.txt).
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// wxWidgets
#include <model/MyTagApp.h>
#include "wx/wx.h"

// svncpp
#include "svncpp/context.hpp"
#include "svncpp/exception.hpp"

// app
#include "action.hpp"
#include "action_event.hpp"
#include "ids.hpp"
#include "threaded_worker.hpp"
#include "tracer.hpp"
#include "utils.hpp"

/**
 * 如何确保svn操作都执行
 * SvnThreadedWorker::WorkThread与SvnThreadedWorker
 */
//event
class SvnThreadedWorker::WorkThread : public wxThread
{
public:
    //
    wxWindow * parent;
    svn::Context * context;
    //
    SvnAction * action;
    Tracer * tracer;
    bool ownContext;
    ActionState state;
    ActionResult result;
    wxString actionName;

    /**
     * constructor
     */
    WorkThread ( wxWindow * parent )
    {
        Init ( parent );
    }

    /**
     * destructor
     */
    ~WorkThread() override
    {
        SetContext ( nullptr, false );
    }

    /**
     * initialize values
     */
    void Init ( wxWindow * parent )
    {
        this->parent = parent;
        context = nullptr;
        action = nullptr;
        tracer = nullptr;
        ownContext = false;
        state = ACTION_NONE;
        result = ACTION_NOTHING;

        //if (Create () != wxTHREAD_NO_ERROR)
        // TODO: error handling
        //
        Create();
        //???
        Run();
    }

    /**
     * set a context. if there is already a context and we
     * own this context, delete it
     *
     * @param ctx new context
     * @param own own new context
     */
    void SetContext ( svn::Context * ctx, bool own )
    {
        //?
        if ( own && ( ownContext != 0 ) ) {
            delete context;
            context = nullptr;
        }

        context = ctx;
        ownContext = own;
    }

    /**
     * Runnable
     * thread execution starts here
     */
    void * Entry() override
    {
        //?
        while ( !TestDestroy() ) {
            ExecuteAction();

            Sleep ( 1000 );
        }
        return nullptr;
    }

    void DeleteAction()
    {
        //
        ActionEvent::Post ( parent, TOKEN_DELETE_ACTION,
                            ( void* ) action );
        action = nullptr;
    }

    /**
     * ActionEvent, SvnAction
     * SvnAction convert to event and post it
     * executes the action if there is any
     * session go
     */
    void ExecuteAction()
    {
        if ( action == nullptr )
            return;
        //?
        ActionEvent event ( parent, TOKEN_ACTION_START );

        {
            //???
            event.init ( parent, TOKEN_ACTION_START,
                         LogItem_Normal, _ ( "Execute:" ), actionName );
            event.Post();
        }

        unsigned int actionFlags = 0;

        try {
            state = ACTION_RUNNING;
            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            if ( !action->Perform() )
                result = ACTION_ERROR;
            else
                result = ACTION_SUCCESS;
            //
            actionFlags = action->GetFlags();

            state = ACTION_NONE;
        } catch ( svn::ClientException & e ) {
            wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
            msg.Printf ( _ ( "Error while performing action: %s" ),
                         errTxt.c_str() );

            event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
            event.Post();

            state = ACTION_NONE;
            result = ACTION_ERROR;
            DeleteAction();
            return;
        } catch ( ... ) {
            wxString msg ( _ ( "Error while performing action." ) );

            event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
            event.Post();

            state = ACTION_NONE;
            result = ACTION_ERROR;
            DeleteAction();
            return;
        }
        //actionFlags
        event.init ( parent, TOKEN_ACTION_END,
                     ( void* ) new unsigned int ( actionFlags ) );
        event.Post();
        DeleteAction();
    }

    /**
     * called when the thread exits - whether it terminates normally or is
     * stopped with Delete() (but not when it is Kill()ed!)
     */
    void OnExit() override
    {
    }

    void TraceError ( const wxString & message ) const
    {
        if ( tracer )
            tracer->TraceError ( message );
    }
};

//
SvnThreadedWorker::SvnThreadedWorker (wxWindow * parent )
{
    //every thread?, create the thread, run the thread, ignore the create
    //m->InitTable, run the thread
    workThread = new WorkThread ( parent );
}

SvnThreadedWorker::~SvnThreadedWorker()
{
    workThread->Delete();
}

//?????
void SvnThreadedWorker::Create (wxWindow * parent )
{
    //start the thread
    //
    workThread->Init ( parent );
}

ActionState SvnThreadedWorker::GetState()
{
    return workThread->state;
}

//current result
ActionResult SvnThreadedWorker::GetResult()
{
    return workThread->result;
}

/**
 * SvnThreadedWorker, AbstractAction
 * Create
 * Perform
 * 拼装action
 */
bool SvnThreadedWorker::Perform ( SvnAction * action_ )
{
    //
    // is there already a thread running?
    if ( workThread->action != nullptr ) {
        //简直了，还有碰撞，应该有序列叠加起来
        workThread->TraceError ( _ ( "Internal Error: There is another action running" ) );
        return false;
    }

    // is there a context? we need one
    if ( workThread->context == nullptr ) {
        workThread->TraceError ( _ ( "Internal Error: no context available" ) );
        return false;
    }
    //如何注入的上下文的
    action_->SetSvnContext(workThread->context);
    workThread->context->reset();

    workThread->result = ACTION_NOTHING;
    workThread->state = ACTION_INIT;

    try {
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        if ( !action_->Prepare() ) {
            //
            workThread->result = ACTION_ABORTED;
            workThread->state = ACTION_NONE;
            delete action_;

            return false;
        }
    } catch ( svn::ClientException & e )  {
        wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
        msg.Printf ( _ ( "Error while preparing action: %s" ), errTxt.c_str() );
        workThread->TraceError ( msg );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete action_;
        return false;
    } catch ( ... ) {
        workThread->TraceError ( _ ( "Error while preparing action." ) );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete action_;
        return false;
    }

    //setup the m->action, use the data( thread ) to post the event
    //Extend SvnAction info
    workThread->actionName = action_->GetName();
    workThread->action = action_;

    return true;
}

void SvnThreadedWorker::SetTracer (Tracer * tracer )
{
    workThread->tracer = tracer;
}

//??
void SvnThreadedWorker::SetSvnContext (svn::Context * context, bool own )
{
    workThread->SetContext ( context, own );
}

svn::Context *SvnThreadedWorker::GetSvnContext() const
{
    return workThread->context;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../rapidsvn-dev.el")
 * end:
 */

/**
 * AbstractActionWorker * CreateActionWorker ( MyTagApp* myTagApp, wxWindow * parent )
{
    return new ThreadedWorker( myTagApp, parent );
}
 */
class ThreadedWorker::WorkThread:public wxThread{
public:
    //
    wxWindow * parent;
    svn::Context * svnContext;
    //
    AbstractAction * action;
    Tracer * tracer;
    bool ownContext;
    ActionState state;
    ActionResult result;
    wxString actionName;
    MyTagApp* myTagApp;
    /**
     * constructor
     */
    WorkThread ( MyTagApp* myTagApp, wxWindow * parent )
    {
        this->myTagApp = myTagApp;
        Init( parent );
    }

    void Init( wxWindow * parent )
    {
        this->parent = parent;
        svnContext = nullptr;
        action = nullptr;
        tracer = nullptr;
        ownContext = false;
        state = ACTION_NONE;
        result = ACTION_NOTHING;

        //if (Create () != wxTHREAD_NO_ERROR)
        // TODO: error handling
        //
        Create();
        //???
        Run();
    }

    /**
     * destructor
     */
    ~WorkThread() override
    {
        SetContext ( nullptr, false );
        //FALSE;
    }

    /**
     * set a context. if there is already a context and we
     * own this context, delete it
     *
     * @param ctx new context
     * @param own own new context
     */
    void SetContext ( svn::Context * ctx, bool own )
    {
        if ( own && ( ownContext != FALSE ) ) {
            //删除原来的context
            delete svnContext;
            svnContext = nullptr;
        }
        //
        svnContext = ctx;
        ownContext = own;
    }

    /**
     * Runnable
     * thread execution starts here
     */
    void * Entry() override
    {
        //?
        while ( !TestDestroy() ) {
            ExecuteAction();

            Sleep ( 1000 );
        }
        return nullptr;
    }

    void DeleteAction()
    {
        //
        ActionEvent::Post ( parent, TOKEN_DELETE_ACTION,
                            ( void* ) action );
        action = nullptr;
    }

    /**
     * ActionEvent, SvnAction
     * SvnAction convert to event and post it
     * executes the action if there is any
     */
    void ExecuteAction()
    {
        if ( action == nullptr )
            return;
        //?
        ActionEvent event ( parent, TOKEN_ACTION_START );

        {
            //???
            event.init ( parent, TOKEN_ACTION_START,
                         LogItem_Normal, _ ( "Execute:" ), actionName );
            event.Post();
        }

        unsigned int actionFlags = 0;

        try {
            state = ACTION_RUNNING;
            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            if ( !action->Perform() )
                result = ACTION_ERROR;
            else
                result = ACTION_SUCCESS;
            //
            ACTION_TYPE actionType = action->getActionType();
            if( actionType == ACTION_SVN )
                actionFlags = (( SvnAction*) action )->GetFlags();

            state = ACTION_NONE;
        } catch ( svn::ClientException & e ) {
            wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
            msg.Printf ( _ ( "Error while performing action: %s" ),
                         errTxt.c_str() );

            event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
            event.Post();

            state = ACTION_NONE;
            result = ACTION_ERROR;
            DeleteAction();
            return;
        } catch ( ... ) {
            wxString msg ( _ ( "Error while performing action." ) );

            event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
            event.Post();

            state = ACTION_NONE;
            result = ACTION_ERROR;
            DeleteAction();
            return;
        }
        //actionFlags
        event.init ( parent, TOKEN_ACTION_END,
                     ( void* ) new unsigned int ( actionFlags ) );
        event.Post();
        DeleteAction();
    }

    /**
     * called when the thread exits - whether it terminates normally or is
     * stopped with Delete() (but not when it is Kill()ed!)
     */
    void OnExit() override
    {
    }

    void TraceError ( const wxString & message ) const
    {
        if ( tracer )
            tracer->TraceError ( message );
    }
};

ThreadedWorker::ThreadedWorker( MyTagApp* myTagApp, wxWindow *parent) {
    //
    workThread = new WorkThread ( myTagApp, parent );
}

ThreadedWorker::~ThreadedWorker() {
    workThread->Delete();
}

//???
void ThreadedWorker::Create(wxWindow *parent) {
    workThread->Init ( parent );
}

ActionState ThreadedWorker::GetState() {
    return ACTION_RUNNING;
}

ActionResult ThreadedWorker::GetResult() {
    return ACTION_NOTHING;
}

void ThreadedWorker::SetTracer(Tracer *tracer) {
    workThread->tracer = tracer;
}

/*
 * how to work?
 * dispatch
 *
 */
bool ThreadedWorker::Perform( AbstractAction * abstractAction) {
    switch ( abstractAction->getActionType() ) {
        case ACTION_NORMAL:
            Perform( (NormalAction* )abstractAction );
            break;
        case ACTION_SVN:
            Perform( (SvnAction* )abstractAction );
            break;
        case ACTION_UNKNOWN:
            break;
        case ACTION_GIT:
            break;
    }
}

//query action
bool ThreadedWorker::Perform( NormalAction *normalAction ) {
    if ( workThread->action != nullptr ) {
        //简直了，还有碰撞，应该有序列叠加起来
        //
        workThread->TraceError ( _ ( "Internal Error: There is another action running" ) );
        return false;
    }
    workThread->result = ACTION_NOTHING;
    workThread->state = ACTION_INIT;

    try {
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        if ( !normalAction->Prepare() ) {
            //
            workThread->result = ACTION_ABORTED;
            workThread->state = ACTION_NONE;
            delete normalAction;

            return false;
        }
    } catch ( svn::ClientException & e )  {
        wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
        msg.Printf ( _ ( "Error while preparing action: %s" ), errTxt.c_str() );
        workThread->TraceError ( msg );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete normalAction;
        return false;
    } catch ( ... ) {
        workThread->TraceError ( _ ( "Error while preparing action." ) );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete normalAction;
        return false;
    }

    //setup the m->action, use the data( thread ) to post the event
    //Extend SvnAction info
    workThread->actionName = normalAction->GetName();
    workThread->action = normalAction;

    return true;
}

//
bool ThreadedWorker::Perform(SvnAction *svnAction) {
    if ( workThread->action != nullptr ) {
        //简直了，还有碰撞，应该有序列叠加起来
        workThread->TraceError ( _ ( "Internal Error: There is another action running" ) );
        return false;
    }

    // is there a context? we need one
    if ( workThread->svnContext == nullptr ) {
        workThread->TraceError ( _ ( "Internal Error: no context available" ) );
        return false;
    }
    //set the action context
    svnAction->SetSvnContext(workThread->svnContext);
    workThread->svnContext->reset();
    //reset the status
    workThread->result = ACTION_NOTHING;
    workThread->state = ACTION_INIT;

    try {
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        if ( !svnAction->Prepare() ) {
            //
            workThread->result = ACTION_ABORTED;
            workThread->state = ACTION_NONE;
            delete svnAction;

            return false;
        }
    } catch ( svn::ClientException & e )  {
        wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
        msg.Printf ( _ ( "Error while preparing action: %s" ), errTxt.c_str() );
        workThread->TraceError ( msg );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete svnAction;
        return false;
    } catch ( ... ) {
        workThread->TraceError ( _ ( "Error while preparing action." ) );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete svnAction;
        return false;
    }

    //setup the m->action, use the data( thread ) to post the event
    //Extend SvnAction info
    workThread->actionName = svnAction->GetName();
    //wait to run by thread
    workThread->action = svnAction;

    return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
 * 如何构造action，填充action，构造action，配置上下文
 * 然后perform( action )
 */
class ContextThreadedWorker::WorkThread : public wxThread
{
public:
    //
    wxWindow * parent;
    MyTagApp* myTagApp;
    //
    svn::Context * svnContext;
    //
    AbstractAction * action;
    GitContext * gitContext;

    //GitAction * gitAction;
    Tracer * tracer;
    bool ownContext;
    ActionState state;
    ActionResult result;
    wxString actionName;

    WorkThread ( MyTagApp* myTagApp, wxWindow * parent )
    {
        Init ( myTagApp, parent );
    }

    //
    ~WorkThread() override
    {
        SetSvnContext ( nullptr, false );
    }

    /**
     * initialize values
     */
    void Init ( MyTagApp* myTagApp, wxWindow * parent )
    {
        this->parent = parent;
        this->myTagApp = myTagApp;
        svnContext = nullptr;
        gitContext = nullptr;
        action = nullptr;
        tracer = nullptr;
        //
        ownContext = false;
        state = ACTION_NONE;
        result = ACTION_NOTHING;

        //if (Create () != wxTHREAD_NO_ERROR)
        // TODO: error handling
        //
        Create();
        //???
        Run();
    }

    /**
     * set a context. if there is already a context and we
     * own this context, delete it
     *
     * @param ctx new context
     * @param own own new context
     */
    void SetSvnContext ( svn::Context * ctx, bool own )
    {
        //?
        if ( own && ( ownContext != 0 ) ) {
            delete svnContext;
            svnContext = nullptr;
        }
        //如何让svnAction关联context
        svnContext = ctx;
        ownContext = own;
    }

    /**
     * Runnable
     * thread execution starts here
     */
    void * Entry() override
    {
        //?
        while ( !TestDestroy() ) {
            ExecuteAction();

            Sleep ( 1000 );
        }
        return nullptr;
    }

    void DeleteAction()
    {
        ActionEvent::Post ( parent, TOKEN_DELETE_ACTION,
                            ( void* ) action );
        action = nullptr;
    }

    /**
     * ActionEvent, SvnAction
     * SvnAction convert to event and post it
     * executes the action if there is any
     * session go
     * NormalAction
     * SvnAction
     * GitAction
     */
    void ExecuteAction()
    {
        if ( action == nullptr )
            return;

        //?
        ActionEvent event ( parent, TOKEN_ACTION_START );

        {
            //???
            event.init ( parent, TOKEN_ACTION_START,
                         LogItem_Normal, _ ( "Execute:" ), actionName );
            event.Post();
        }

        unsigned int actionFlags = 0;

        try {
            state = ACTION_RUNNING;
            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            if ( !action->Perform() )
                result = ACTION_ERROR;
            else
                result = ACTION_SUCCESS;
            if( action->getActionType()==ACTION_SVN )
                actionFlags = ((SvnAction*)action)->GetFlags();

            state = ACTION_NONE;
        } catch ( svn::ClientException & e ) {
            wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
            msg.Printf ( _ ( "Error while performing action: %s" ),
                         errTxt.c_str() );

            event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
            event.Post();

            state = ACTION_NONE;
            result = ACTION_ERROR;
            DeleteAction();
            return;
        } catch ( ... ) {
            wxString msg ( _ ( "Error while performing action." ) );

            event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
            event.Post();

            state = ACTION_NONE;
            result = ACTION_ERROR;
            DeleteAction();
            return;
        }
        //actionFlags
        event.init ( parent, TOKEN_ACTION_END,
                     ( void* ) new unsigned int ( actionFlags ) );
        event.Post();
        DeleteAction();
    }

    void ExecuteAction( NormalAction* action1 ){

    }

    void ExecuteAction( SvnAction* action ){

    }

    void ExecuteAction( GitAction* action1 ){

    }
    /**
     * called when the thread exits - whether it terminates normally or is
     * stopped with Delete() (but not when it is Kill()ed!)
     */
    void OnExit() override
    {
    }

    void TraceError ( const wxString & message ) const
    {
        if ( tracer )
            tracer->TraceError ( message );
    }
};

//
ContextThreadedWorker::ContextThreadedWorker ( MyTagApp* myTagApp, wxWindow * parent )
{
    //every thread?, create the thread, run the thread, ignore the create
    //m->InitTable, run the thread
    workThread = new WorkThread ( myTagApp, parent );
}

ContextThreadedWorker::~ContextThreadedWorker()
{
    workThread->Delete();
}

//?????
void ContextThreadedWorker::Create ( MyTagApp* myTagApp, wxWindow * parent )
{
    //start the thread
    //
    workThread->Init ( myTagApp, parent );
}

void ContextThreadedWorker::Create ( wxWindow * parent )
{
    //start the thread
    //
    //workThread->Init ( myTagApp, parent );
    throw "Not Implemented!";
}

ActionState ContextThreadedWorker::GetState()
{
    return workThread->state;
}

//current result
ActionResult ContextThreadedWorker::GetResult()
{
    return workThread->result;
}

void ContextThreadedWorker::SetTracer (Tracer * tracer )
{
    workThread->tracer = tracer;
}

//??
void ContextThreadedWorker::SetSvnContext (svn::Context * context, bool own )
{
    workThread->SetSvnContext ( context, own );
}

svn::Context *ContextThreadedWorker::GetSvnContext() const
{
    return workThread->svnContext;
}

//action and event
bool ContextThreadedWorker::Perform( NormalAction *normalAction ) {
    if ( workThread->action != nullptr ) {
        //简直了，还有碰撞，应该有序列叠加起来
        workThread->TraceError ( _ ( "Internal Error: There is another action running" ) );
        return false;
    }
    workThread->result = ACTION_NOTHING;
    workThread->state = ACTION_INIT;

    try {
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        if ( !normalAction->Prepare() ) {
            //
            workThread->result = ACTION_ABORTED;
            workThread->state = ACTION_NONE;
            delete normalAction;

            return false;
        }
    } catch ( svn::ClientException & e )  {
        wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
        msg.Printf ( _ ( "Error while preparing action: %s" ), errTxt.c_str() );
        workThread->TraceError ( msg );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete normalAction;
        return false;
    } catch ( ... ) {
        workThread->TraceError ( _ ( "Error while preparing action." ) );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete normalAction;
        return false;
    }

    //setup the m->action, use the data( thread ) to post the event
    //Extend SvnAction info
    workThread->actionName = normalAction->GetName();
    workThread->action = normalAction;

    return true;
}

/**
 * SvnThreadedWorker, AbstractAction
 * Create
 * Perform
 * 拼装action
 */
bool ContextThreadedWorker::Perform ( SvnAction * action_ )
{
    //
    // is there already a thread running?
    if ( workThread->action != nullptr ) {
        //简直了，还有碰撞，应该有序列叠加起来
        workThread->TraceError ( _ ( "Internal Error: There is another action running" ) );
        return false;
    }

    // is there a context? we need one
    if ( workThread->svnContext == nullptr ) {
        workThread->TraceError ( _ ( "Internal Error: no context available" ) );
        return false;
    }
    //如何注入的上下文的
    //set the action context
    //build the action
    action_->SetSvnContext(workThread->svnContext);
    //传递过来
    workThread->svnContext->reset();
    //
    workThread->result = ACTION_NOTHING;
    workThread->state = ACTION_INIT;

    try {
        //action context
        if ( !action_->Prepare() ) {
            //
            workThread->result = ACTION_ABORTED;
            workThread->state = ACTION_NONE;
            delete action_;

            return false;
        }
    } catch ( svn::ClientException & e )  {
        wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
        msg.Printf ( _ ( "Error while preparing action: %s" ), errTxt.c_str() );
        workThread->TraceError ( msg );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete action_;
        return false;
    } catch ( ... ) {
        workThread->TraceError ( _ ( "Error while preparing action." ) );

        workThread->result = ACTION_ERROR;
        workThread->state = ACTION_NONE;
        delete action_;
        return false;
    }

    //setup the m->action, use the data( thread ) to post the event
    //Extend SvnAction info
    workThread->actionName = action_->GetName();
    workThread->action = action_;

    return true;
}

bool ContextThreadedWorker::Perform(GitAction *gitAction) {
    return false;
}

GitContext *ContextThreadedWorker::GetGitContext() const {
    return workThread->gitContext;
}

void ContextThreadedWorker::SetGitContext(GitContext *context, bool own) {

}
